/*
 * complex.h
 *
 *  Created on: Dec 7, 2011
 *      Author: Zhang
 */

#ifndef COMPLEX_H_
#define COMPLEX_H_
#define REF(x) &x

// Depending on whether we're running inside the CUDA compiler, define the __host_
// and __device__ intrinsics, otherwise just make the functions static to prevent
// linkage issues (duplicate symbols and such)
#ifdef __CUDACC__
#define HOST __host__
#define DEVICE __device__
#define HOSTDEVICE __host__ __device__
#else
#define HOST  inline
#define DEVICE  inline
#define HOSTDEVICE inline
#endif

// Struct alignment is handled differently between the CUDA compiler and other
// compilers (e.g. GCC, MS Visual C++ .NET)
#ifdef __CUDACC__
#define ALIGN(x)  __align__(x)
#else
#if defined(_MSC_VER) && (_MSC_VER >= 1300)
// Visual C++ .NET and later
#define ALIGN(x) __declspec(align(x))
#else
#if defined(__GNUC__)
// GCC
#define ALIGN(x)  __attribute__ ((aligned (x)))
#else
// all other compilers
#define ALIGN(x)
#endif
#endif
#endif

template<typename T>
struct ALIGN(8) Complex{
	T x;
	T y;

	HOSTDEVICE Complex<T>& operator=(const Complex<T> &c){
		x = c.x;
		y = c.y;
		return *this;
	}
	HOSTDEVICE Complex<T>& operator =(const T &t){
		x = t;
		y = 0;
	}

	HOSTDEVICE Complex<T>& operator +(const Complex<T> &c){
		Complex<T> result = {x + c.x, y + c.y};
		return result;
	}
	HOSTDEVICE Complex<T>& operator +(const T &t){
		return {x + t, y};
	}

	HOSTDEVICE Complex<T>& operator +=(const Complex<T> &c){
		x += c.x;
		y += c.y;
		return *this;
	}
	HOSTDEVICE Complex<T>& operator +=(const T &t){
		x += t;
		return *this;
	}
	HOSTDEVICE Complex<T>& operator -(const Complex<T> &c){
		Complex<T> result = {x-c.x, y-c.y};
		return result;
	}
	HOSTDEVICE Complex<T>& operator -(const T &t){
		Complex<T> result = {x-t, y};
		return result;
	}

	HOSTDEVICE Complex<T>& operator -=(const Complex<T> c){
		x -= c.x;
		y -= c.y;
		return *this;
	}
	HOSTDEVICE Complex<T>& operator -=(const T t){
		x -= t;
		return *this;
	}

	HOSTDEVICE Complex<T>& operator *(const Complex<T> c){
		Complex<T> result = {x*c.x - y*c.y, x*c.y+y*c.x};
		return result;
	}

	HOSTDEVICE Complex<T>& operator *(const T t){
		Complex<T> result = {x*t, y*t};
		return result;
	}

	HOSTDEVICE Complex<T>& operator *=(const Complex<T> c){
		x *= c.x;
		y *= c.y;
		return *this;
	}
	HOSTDEVICE Complex<T>& operator *=(const T t){
		x *= t;
		y *= t;
		return *this;
	}
};

#endif /* COMPLEX_H_ */
